#include "rtp2flv.h"

int getfilesize(FILE * fd){
	int len = 0;
	fseek(fd, 0, SEEK_END);
	len = ftell(fd);
	fseek(fd, 0, SEEK_SET);
	return len;
}

//return,NULL
unsigned char *getbuffer(int file_size){
	unsigned char *buf = (unsigned char*)malloc(file_size);
	return buf;
}
void freebuffer(char *ptr){
	if (ptr != NULL)
	{
		free(ptr);
	}
	return;
}

int is_startcode(rtpbuf_t *buf){
	if (buf->bufsize < 4)
	{
		return -1;
	}
	if ( *(int*) (buf->buf + buf->bufnextpos) == 0x01000000 )
	{
		return 1;
	}
	else{
		return 0;
	}
}

int getpacket_startpos(rtpbuf_t *buf){
	rtpbuf_t *ptmp = buf;
	int ret;
	buf->bufnextpos += 4;
	buf->bufsize -= 4;
	do 
	{
		ret = is_startcode(buf);
		if (ret<0 || ret == 1)
		{
			return ret;
		}
		buf->bufsize--;
		buf->bufnextpos++;
	} while (1);

	return -1;
}

int getpacket(rtpbuf_t * rtpbufctx, packet_t * packetctx){
	int ret;
	int packetstartpos;
	int packetendpos;
	ret = getpacket_startpos(rtpbufctx);
	if (ret != 1){
		//eof
		rtpbufctx->bufnextpos = rtpbufctx->bufsize;
	}
	packetctx->packetsize = rtpbufctx->bufnextpos - rtpbufctx->bufpos;
	packetctx->packetbuf = rtpbufctx->buf + rtpbufctx->bufpos;
	return ret;
}

/*
params:
in:filefd
out:flvfd
return:
0
-1
*/
int rtp2flv(FILE* rtp_fd, char *flv_fd, unsigned int rtptimebase){
	//step 0. init
	int ret;
	int filesize;
	int payloadoffset;
	rtpbuf_t rtpReadbuf;
	x264_nal_t nalPacket[2] = {0};
	//FILE*fptest = fopen("C:/Users/dodo/Documents/Visual Studio 2013/Projects/rtp2flv/rtp2flv/test.h264", "wb");
	flv_hnd_t *p_handle;
	rtp2flvCtx_t rtpCtx = { 0 };
	rtp2flvCtx_t *p_rtp = &rtpCtx;
	rtpReadbuf.bufsize = getfilesize(rtp_fd);

        printf("123456\n");

	if (rtpReadbuf.bufsize<=0)
	{
		return -1;
	}
	rtpReadbuf.buf = getbuffer(rtpReadbuf.bufsize);
	if (rtpReadbuf.bufsize == NULL)
	{
		return -1;
	}
	ret = fread(rtpReadbuf.buf, 1, rtpReadbuf.bufsize, rtp_fd);
	if (ret != rtpReadbuf.bufsize)
	{
		return -1;
	}
	rtpReadbuf.bufpos = 0;
	p_rtp->p_video_frame = (uint8_t*)malloc(MAX_VIDEO_FRAME_SIZE);
	if (p_rtp->p_video_frame == NULL)
	{
		return -1;
	}
	p_rtp->rtptimebase = rtptimebase;
	//p_rtp->rtppayload = rtppayload;
	//p_rtp->fps = fps;

	//flv
	InitFirstPos(&rtpReadbuf);
	ret = open_file(flv_fd, &p_handle);
	if (ret != 0){
		return -1;
	}
	//p_handle->fps = fps;
	set_script_param(p_handle, 640, 480);
	//step 1.read rtp file,prepare input data
	while (1)
	{
		packet_t packet = { 0 };
		rtp_header_t rtp_header = { 0 };
		char p_save_buf[4096] = { 0 };
		int i_use_data = 0;
		unsigned char* p_buf = NULL;
		rtpReadbuf.bufpos = rtpReadbuf.bufnextpos + 4;
		ret = getpacket(&rtpReadbuf, &packet);
		if (ret != 1)
		{
			break;
		}
		payloadoffset = get_rtp_header(&rtp_header, packet.packetbuf, packet.packetsize);
		if (payloadoffset <12){
			printf("get rtp header error1\n");
			return -1;
		}
		else if (payloadoffset >= packet.packetsize)
		{
			printf("get_rtp_header error2 \n");
			return -1;
		}
		//if (rtp_header.i_pt == p_rtp->rtppayload)// VIDEO
		if (1)
		{
			if (p_rtp->has_sps == 0 )
			{
				if ( ((packet.packetbuf[payloadoffset] & 0x1f) != 7))
				{
					continue;
				}
				p_rtp->has_sps = 1;
				//sps
				nalPacket[0].p_payload = packet.packetbuf + payloadoffset;
				nalPacket[0].i_payload = packet.packetsize - payloadoffset;
				nalPacket[0].i_type = 7;
				continue;
			}
			if (p_rtp->has_pps == 0)
			{
				if (((packet.packetbuf[payloadoffset] & 0x1f) != 8))
				{
					continue;
				}
				p_rtp->has_pps = 1;
				//pps
				nalPacket[1].p_payload = packet.packetbuf + payloadoffset;
				nalPacket[1].i_payload = packet.packetsize - payloadoffset;
				nalPacket[1].i_type = 7;
				write_h264_headers(p_handle, nalPacket);
				continue;
			}
			if (p_rtp->i_video_time_stamp == 0)
			{
				p_rtp->i_video_time_stamp = rtp_header.i_timestamp;
				p_rtp->i_video_frame_index = 0;
				p_rtp->i_video_time_startoffset = rtp_header.i_timestamp;
				p_handle->i_video_time_startoffset = rtp_header.i_timestamp;
				//memcpy(p_rtp->p_video_frame + p_rtp->i_video_frame_index, p_save_buf, i_size);
				//p_rtp->i_video_frame_index += i_size;
				p_rtp->i_slice_first_nalu = 1;
			}
			int i_size = RtpTo264(packet.packetbuf , packet.packetsize, p_save_buf, p_rtp,payloadoffset);
			if (i_size < 0)
			{
				printf("RtpTo264 error!\n");
				return -1;
			}
			//printf("i_recv_size--2 = %d, i_size = %d, nalu = %d\n", i_recv_size, i_size, p_rtp->i_nalu_ok_flag );
			if (p_rtp->i_video_time_stamp != rtp_header.i_timestamp || packet.packetbuf[payloadoffset] == 0x78)
			{
				if (p_rtp->i_video_frame_index > 0)
				{
					//flvenc(p_rtp, flv_fd);
					nalPacket[0].p_payload = p_rtp->p_video_frame ;
					nalPacket[0].i_payload = p_rtp->i_video_frame_index ;
					nalPacket[0].i_type = p_rtp->p_video_frame[4] & 0x1f;
					{
					//	fwrite(p_rtp->p_video_frame, 1, p_rtp->i_video_frame_index, fptest);
					//	fflush(fptest);
					}
					write_h264_frame(p_rtp,p_handle, nalPacket[0]);
				}
				p_rtp->i_video_frame_index = 0;
				p_rtp->i_video_time_stamp = rtp_header.i_timestamp;
				memcpy(p_rtp->p_video_frame + p_rtp->i_video_frame_index, p_save_buf, i_size);
				p_rtp->i_video_frame_index += i_size;
				p_rtp->i_slice_first_nalu = 1;
			}
			else
			{
				memcpy(p_rtp->p_video_frame + p_rtp->i_video_frame_index, p_save_buf, i_size);
				p_rtp->i_video_frame_index += i_size;
			}
		}
			
	}
	close_file(p_handle);
	return 0;
	//step 2.process input data by rtp packet

	//step 3.output flvfile by frame

}
